#ifndef DEGREE_H
#define DEGREE_H

#include "Framework/Prerequisites.h"

namespace tyro
{
	namespace Math
	{
		template <class T>
		class Degree
		{
		public:

			T	degree;

			/* Default Constructor */
			Degree<T>( T deg=0 ) : degree(deg) {}

			/* Multi-Contructors */
			Degree<T>( const Radian<T>& rad );

			/* Assignment Operators */
			inline Degree<T>& operator = ( const T& val ) { degree = val; return *this; }
			inline Degree<T>& operator = ( const Degree<T>& deg ) { degree = deg.degree; return *this; }
			inline Degree<T>& operator = ( const Radian<T>& rad );

			/* Relational and Equality Operators */
			inline bool operator == ( const Degree<T>& deg ) const { return degree == deg.degree; }
			inline bool operator != ( const Degree<T>& deg ) const { return degree != deg.degree; }
			inline bool operator <  ( const Degree<T>& deg ) const { return degree <  deg.degree; }
			inline bool operator <= ( const Degree<T>& deg ) const { return degree <= deg.degree; }
			inline bool operator >  ( const Degree<T>& deg ) const { return degree >  deg.degree; }
			inline bool operator >= ( const Degree<T>& deg ) const { return degree >= deg.degree; }

			/* Binary Arithmetic Operators */
			inline const Degree<T>& operator + () const { return *this; }
			inline Degree<T> operator + ( const Degree<T>& deg ) const { return Degree<T>( degree + deg.degree ); }
			inline Degree<T> operator + ( const Radian<T>& rad ) const;
			inline Degree<T> operator - () const { return Degree<T>(-degree); }
			inline Degree<T> operator - ( const Degree<T>& deg ) const { return Degree<T>( degree - deg.degree ); }
			inline Degree<T> operator - ( const Radian<T>& rad ) const;
			inline Degree<T> operator * ( T val ) const { return Degree<T> ( degree * val ); }
			inline Degree<T> operator * ( const Degree<T>& deg ) const { return Degree<T> ( degree * deg.degree ); }
			inline Degree<T> operator / ( T val ) const { return Degree<T>( degree / val ); }

			/* Compound Assignment Operators */
			inline Degree<T>& operator += ( const Degree<T>& deg ) { degree += deg.degree; return *this; }
			inline Degree<T>& operator += ( const Radian<T>& rad );
			inline Degree<T>& operator -= ( const Degree<T>& deg ) { degree -= deg.degree; return *this; }
			inline Degree<T>& operator -= ( const Radian<T>& rad );
			inline Degree<T>& operator *= ( T val ) { degree *= val; return *this; }
			inline Degree<T>& operator /= ( T val ) { degree /= val; return *this; }

			T ToDegrees() const { return degree; }
			T ToRadians() const;


		protected:
		private:
		};

		template <class T>
		tyro::Math::Degree<T>::Degree( const Radian<T>& rad )
		{
			return Degree<T>(Math::RadiansToDegrees(rad));
		}

		template <class T>
		inline Degree<T>& tyro::Math::Degree<T>::operator = ( const Radian<T>& rad )
		{
			degree = Math::RadiansToDegrees(rad);
			return *this;
		}

		template <class T>
		inline Degree<T> tyro::Math::Degree<T>::operator + ( const Radian<T>& rad ) const
		{
			return Degree(degree + Math::RadiansToDegrees(rad));
		}

		template <class T>
		inline Degree<T> tyro::Math::Degree<T>::operator - ( const Radian<T>& rad ) const
		{
			return Degree(degree - Math::RadiansToDegrees(rad));
		}

		template <class T>
		inline Degree<T>& tyro::Math::Degree<T>::operator += ( const Radian<T>& rad )
		{
			degree += Math::RadiansToDegrees(rad);
			return *this;
		}

		template <class T>
		inline Degree<T>& tyro::Math::Degree<T>::operator -= ( const Radian<T>& rad )
		{
			degree = Math::RadiansToDegrees(rad);
			return *this;
		}
	}
}
#endif